﻿using System;
using System.IO;
using System.IO.Packaging;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Net.Mime;
using Snowdreamist.ComponentModel;

namespace Snowdreamist.Windows.Document
{
    public class RichTextDocumentPersistingContext : IDisposable
    {
        internal RichTextDocumentPersistingContext(Package package)
        {
            if (package == null)
                throw new ArgumentNullException("package");
            this._package = package;
            this.Resources = new DocumentResources();
        }

        public Stream BeginWriteResource(DependencyObject holdRefResDpObj, string key, string type)
        {
            if (holdRefResDpObj == null)
                throw new ArgumentNullException("holdRefResDpObj");
            if (!(holdRefResDpObj is IHoldReferencedResource))
                throw new ArgumentException("Wrong Type");
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("Invalid key");
            if (string.IsNullOrWhiteSpace(type))
                throw new ArgumentNullException("type");
            // get guid
            var resKey = RichTextDocument.GetResourceKey(holdRefResDpObj);
            if (resKey == Guid.Empty)
            {
                // assign new guid
                resKey = Guid.NewGuid();
                RichTextDocument.SetResourceKey(holdRefResDpObj, resKey);
            }
            // get resource manifest
            DocumentResource resource = null;
            if (!this.Resources.Collections.TryGetValue(resKey, out resource) || resource == null)
            {
                resource = new DocumentResource() { Key = resKey, Values = new List<DocumentMetaResource>() };
                this.Resources.Collections[resKey] = resource;
            }
            // check key
            if (resource.Values.Where(p => p.Key == key).Count() != 0)
                throw new ArgumentException("Duplicated key");
            // get random filename
            string filename = "Resource-{0}" + ThreadSafeRandom.Next().ToString();
            Uri resourceUri = new Uri(string.Format(Utility.ResourceUriFormat, filename), UriKind.Relative);
            // write resources
            var part = this._package.CreatePart(resourceUri, type);
            // add manifest
            resource.Values.Add(new DocumentMetaResource()
            {
                Key = key,
                Type = type,
                Filename = filename
            });
            // return part stream
            return part.GetStream();
        }

        public void Dispose() { }

        internal DocumentResources Resources { get; private set; }

        #region private

        private Package _package;

        #endregion
    }
}
